<script setup>
import {reactive, ref} from "vue";
import {ElMessage} from "element-plus";
import {httpGet, httpPost} from "@/utils/http.js";
import {Delete, Plus} from "@element-plus/icons-vue";
import {isImage, removeArrayItem} from "@/utils/libs.js";
import {GetFileIcon} from "@/store/system.js";
import { checkSession } from "@/store/cache";
import { useSharedStore } from "@/store/sharedata";
// 文件选择组件，用于在聊天或编辑器中插入文件

const props = defineProps({
  // 用户Id
  userId: Number,
})

// 定义selected事件，用于向父组件传递选择的文件
const emits = defineEmits(['selected'])
// 控制对话框显示
const show = ref(false)
// 滚动条引用
const scrollbarRef = ref(null)
// 文件数据
const fileData = reactive({
  items: [], // 文件列表
  page: 1, // 当前页码
  isLastPage: true, // 是否最后一页
})
const store = useSharedStore();
// 查询文件信息
const fetchFiles = (pageNo) => {
  checkSession().then(() => {
    console.log(111)
    show.value = true
    httpPost('/api/file/list', {page: pageNo || 1, page_size: 5}).then(res => {
      const {items, page, total_page} = res.data
      // 处理分页数据
      if (page === 1) {
        // 第一页直接替换
        fileData.items = items
      } else {
        // 把查询出来的数据进行追加
        fileData.items = [...fileData.items, ...items]
      }
      // 更新是否最后一页
      fileData.isLastPage = (page === total_page)
      if (!fileData.isLastPage) {
        fileData.page = page + 1 // 更新下一页页码
      }
    }).catch(e => {
      ElMessage.error('查询文件列表失败：' + e.message)
    })
  }).catch(() => {
    console.log(111)
    store.setShowLoginDialog(true)
  })
}

// 滚动事件处理，主要用于实现滚动到底部自动加载更多数据的功能
const onScroll = (options) => {
  // scrollbarRef 是对 Element Plus 的 <el-scrollbar> 组件的引用
  // wrapRef 是滚动条组件内部的包裹容器 DOM 元素
  const wrapRef = scrollbarRef.value.wrapRef
  // wrapRef.scrollTop: 当前垂直滚动位置（从顶部滚动的像素数）
  // wrapRef.clientHeight: 滚动容器可视区域的高度
  // 计算滚动位置占可视区域高度的百分比
  // 将计算结果赋值给 scrollbarRef.value.moveY 以更新滚动条位置指示器
  scrollbarRef.value.moveY = wrapRef.scrollTop * 100 / wrapRef.clientHeight
  // wrapRef.scrollLeft: 当前水平滚动位置（从左侧滚动的像素数）
  // wrapRef.clientWidth: 滚动容器可视区域的宽度
  // 计算滚动位置占可视区域宽度的百分比
  // 将计算结果赋值给 scrollbarRef.value.moveX 以更新水平滚动条位置
  scrollbarRef.value.moveX = wrapRef.scrollLeft * 100 / wrapRef.clientWidth
  // wrapRef.scrollHeight: 滚动容器内容的总高度（包括不可见部分）
  // wrapRef.clientHeight: 滚动容器可视区域的高度
  // poor 表示从顶部到底部的最大可滚动距离（内容总高度减去可视区域高度）
  const poor = wrapRef.scrollHeight - wrapRef.clientHeight
  // options.screenTop: 当前滚动位置（从顶部滚动的像素数）
  // options.screenTop + 2 >= poor: 判断当前滚动位置是否接近或超过最大可滚动距离，+2 是为了在接近底部时提前触发加载（容错机制）
  if (options.screenTop + 2 >= poor && !fileData.isLastPage) {
    // 调用fetchFiles方法，传入当前页码（fileData.page）加载下一页数据。
    fetchFiles(fileData.page)
  }
}

// 文件上传
const afterRead = (file) => {
  const formData = new FormData()
  formData.append('file', file.file, file.name)
  // 执行上传操作
  httpPost('api/file/upload', formData).then(res => {
    // 新文件添加到列表开头
    fileData.items.unshift(res.data)
    ElMessage.success({message: '上传成功', duration: 500})
  }).catch(e => {
    ElMessage.error('图片上传失败：' + e.message)
  })
}

// 删除文件
const removeFile = (file) => {
  httpGet('api/file/remove?id=' + file.id).then(() => {
    // 从文件列表中移除文件
    fileData.items = removeArrayItem(fileData.items, file, (v1, v2) => {
      return v1.id === v2.id
    })
    ElMessage.success('文件删除成功')
    fetchFiles(1)
  }).catch(e => {
    ElMessage.error("文件删除失败：" + e.message)
  })
}

// 选择文件
const insertURL = (file) => {
  // 关闭弹框
  show.value = false
  // 如果是相对路径处理成绝对路径
  if (file.url.indexOf('http') === -1) {
    file.url = location.protocol + "//" + location.port + file.url
  }
  // 触发selected事件，传递选择的文件
  emits('selected', file)
}

</script>

<template>
  <el-container class="file-select-box">
    <!-- 上传附件按钮  -->
    <a class="file-upload-img" @click="fetchFiles(1)">
      <i class="iconfont icon-attachment-st"></i>
    </a>
    <el-dialog class="file-list-dialog" v-model="show" :close-on-click-modal="true" :show-close="true" :width="800"
               title="文件管理">
      <!-- max-height：滚动条最大高度  @scroll 当触发滚动事件时，返回滚动的距离	-->
      <el-scrollbar ref="scrollbarRef" max-height="80vh" style="height: 100%" @scroll="onScroll">
        <div class="file-list">
          <el-row :gutter="20">
            <el-col :span="3">
              <!-- 文件上传 -->
              <div class="grid-content">
                <el-upload class="avatar-uploader" :auto-upload="true" :show-file-list="false" :http-request="afterRead"
                           accept=".doc,.docx,.jpg,.png,.jpeg,.xls,.xlsx,.ppt,.pptx,.pdf,.mp4,.mp3">
                  <el-icon class="avatar-uploader-icon">
                    <Plus/>
                  </el-icon>
                </el-upload>
              </div>
            </el-col>
            <!-- 显示文件列表 -->
            <el-col :span="3" v-for="file in fileData.items" :key="file.url">
              <div class="grid-content">
                <el-tooltip class="box-item" effect="dark" :content="file.name" placement="top">
                  <el-image :src="file.url" fit="cover" v-if="isImage(file.ext)" @click="insertURL(file)"/>
                  <el-image :src="GetFileIcon(file.ext)" fit="cover" v-else @click="insertURL(file)"/>
                </el-tooltip>
                <div class="opt">
                  <el-button type="danger" size="small" :icon="Delete" @click="removeFile(file)" circle/>
                </div>
              </div>
            </el-col>
          </el-row>
          <el-row justify="center" v-if="!fileData.isLastPage" @click="fetchFiles(fileData.page)">
            <el-link>加载更多</el-link>
          </el-row>
        </div>
      </el-scrollbar>
    </el-dialog>
  </el-container>
</template>

<style lang="stylus">

.file-select-box {
  .file-upload-img {
    .iconfont {
      font-size: 19px;
    }
  }

  .el-dialog {

    .el-dialog__body {
      //padding 0
      overflow hidden

      .file-list {
        margin-right 10px

        .grid-content {
          margin-bottom 10px
          position relative

          .avatar-uploader {
            width 100%
            display: flex;
            justify-content: center;
            align-items: center;
            border 1px dashed #e1e1e1
            border-radius 6px

            .el-upload {
              width 100%
              height 80px
            }
          }

          .el-image {
            width 100%
            height 80px
            border 1px solid #ffffff
            border-radius 6px
            cursor pointer

            &:hover {
              border 1px solid #20a0ff
            }

          }

          .iconfont {
            color #20a0ff
            font-size 40px
          }

          .opt {
            display none
            position absolute
            top 5px
            right 5px
          }

          &:hover {
            .opt {
              display block
            }
          }
        }
      }

    }
  }
}
</style>